#pragma once
#include <vector>
#include <string>
#include "SP3Interpolator.h"

/**
 * @class GPSSatelliteOrbit
 * @brief GPS卫星轨道计算类
 */
class GPSSatelliteOrbit {
public:
    GPSSatelliteOrbit();
    ~GPSSatelliteOrbit();
    
    /**
     * @brief 设置轨道参数
     * @param params 导航消息参数向量
     */
    void setOrbitParams(const std::vector<double>& params);
    
    /**
     * @brief 计算指定时间的卫星位置
     * @param time GPS时间(周内秒)
     * @return ECEF坐标[x,y,z](m)
     */
    std::vector<double> computePosition(double time) const;
    
    /**
     * @brief 计算卫星速度
     * @param time GPS时间(周内秒)
     * @return ECEF速度[vx,vy,vz](m/s)
     */
    std::vector<double> computeVelocity(double time) const;
    
    /**
     * @brief 同时计算卫星位置和速度
     * @param time GPS时间(周内秒)
     * @param pos 输出位置[x,y,z](m)
     * @param vel 输出速度[vx,vy,vz](m/s)
     * @param dts 输出钟差(s)和钟漂(s/s)，如果为nullptr则不输出
     * @return 计算是否成功
     */
    bool computePosVel(double time, std::vector<double>& pos, std::vector<double>& vel, std::vector<double>* dts = nullptr) const;
    
    /**
     * @brief 获取轨道参考时间
     * @return 轨道参考时间(周内秒)
     */
    double getReferenceTime() const { return toe_; }
    
    /**
     * @brief 设置卫星PRN号
     * @param prn 卫星PRN号
     */
    void setPRN(const std::string& prn) { prn_ = prn; }
    
    /**
     * @brief 获取卫星PRN号
     * @return 卫星PRN号
     */
    std::string getPRN() const { return prn_; }

    // 添加新方法
    void setSP3Interpolator(SP3Interpolator* sp3) { sp3Interpolator_ = sp3; }
    void setUsePreciseOrbit(bool use) { usePreciseOrbit_ = use; }

private:
    std::string prn_;     // 卫星PRN号
    double toe_;          // 星历参考时间(GPS周内秒)
    double sqrtA_;        // 轨道长半轴平方根(m^0.5)
    double e_;            // 轨道偏心率
    double i0_;           // 轨道倾角(rad)
    double OMEGA0_;       // 升交点赤经(rad)
    double omega_;        // 近地点角距(rad)
    double M0_;           // 平近点角(rad)
    
    double deltan_;       // 平均角速度改正项(rad/s)
    double idot_;         // 轨道倾角变化率(rad/s)
    double OMEGA_DOT_;    // 升交点赤经变化率(rad/s)
    
    double cuc_;          // 纬度幅角余弦调和改正项(rad)
    double cus_;          // 纬度幅角正弦调和改正项(rad)
    double crc_;          // 径向余弦调和改正项(m)
    double crs_;          // 径向正弦调和改正项(m)
    double cic_;          // 轨道倾角余弦调和改正项(rad)
    double cis_;          // 轨道倾角正弦调和改正项(rad)
    
    // 钟差参数
    double af0_;          // 钟差多项式常数项(s)
    double af1_;          // 钟差多项式一次项(s/s)
    double af2_;          // 钟差多项式二次项(s/s^2)
    
    // 常量
    static constexpr double GM = 3.986005e14;     // 地球引力常数(m^3/s^2)
    static constexpr double OMEGA_E = 7.2921151467e-5;  // 地球自转角速度(rad/s)
    static constexpr double C_LIGHT = 299792458.0;      // 光速(m/s)
    
    SP3Interpolator* sp3Interpolator_ = nullptr;  // SP3插值器指针
    bool usePreciseOrbit_ = false;                // 是否使用精密星历
    
    /**
     * @brief 计算开普勒轨道参数
     * @param time GPS时间(周内秒)
     * @param pos 输出位置[x,y,z](m)
     * @param vel 输出速度[vx,vy,vz](m/s)
     */
    void computeKeplerOrbit(double time, std::vector<double>& pos, std::vector<double>* vel = nullptr) const;
    
    /**
     * @brief 计算卫星钟差
     * @param time GPS时间(周内秒)
     * @return 卫星钟差(秒)
     */
    double computeSatClockBias(double time) const;
    
    /**
     * @brief 解开普勒方程
     * @param M 平近点角(rad)
     * @param e 偏心率
     * @return 偏近点角E(rad)
     */
    double solveKeplerEquation(double M, double e) const;
}; 